package com.ctrip.cap.internal.appium.suite;

import com.ctrip.cap.common.exception.CapException;
import com.ctrip.cap.device.Device;
import com.ctrip.cap.device.DeviceStoreFactory;
import com.ctrip.cap.device.DeviceStoreFactory.MobilePlatformType;
import com.ctrip.cap.internal.appium.suite.android.AndroidStartupListener;
import com.ctrip.cap.internal.appium.suite.ios.IOSStartupListener;
import com.ctrip.cap.internal.appium.test.PrepareAppiumDriver;
import com.ctrip.cap.internal.performance.Profilers;
import com.ctrip.cap.internal.suite.JobSetUpListener;
import com.ctrip.cap.internal.suite.SuiteManListener;
import com.ctrip.cap.lanucher.AppiumConfig;
import com.ctrip.cap.lanucher.AppiumConfig.DriverType;
import com.ctrip.cap.lanucher.AppiumServer;
import com.ctrip.cap.lanucher.LinuxAppiumServer;
import com.ctrip.cap.lanucher.MacAppiumServer;
import com.ctrip.cap.lanucher.WinAppiumServer;
import com.google.common.collect.Maps;

import org.apache.commons.exec.OS;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.ISuite;
import org.testng.ISuiteListener;

import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javassist.bytecode.stackmap.TypeData.ClassName;

/**
 * app uri download
 *
 * @author ltyao
 * @see PrepareAppiumDriver
 */
public class AppiumSuiteListener implements ISuiteListener {

	static final Logger logger = LoggerFactory
			.getLogger(AppiumSuiteListener.class);

	private final String PROPERTIES_CONFIG_FILE = "/config/cap.properties";

	protected JobSetUpListener jobSetUpListener = new JobSetUpListener();

	private static final Map<Device, AppiumServer> appiumServers = new HashMap<>();

	// private static String REPORT_URL =
	// "http://autotest.sh.ctriptravel.com/Pages/Reports/CILogReport.aspx?JobID=";
	@Override
	public void onStart(ISuite suite) {

		logger.info("Order debug {}", Profilers.listenerOrder());

		jobSetUpListener.onExecutionStart();
		// Get TestNG Config info
		Profilers.preAppium().start("resolveAppiumconfig");

		Map<String, String> configVals = updateConfigByPropertiesFile(suite);

		AppiumConfig config = new AppiumConfig(configVals);

		logger.info("read appium config parameter from xmlsuite file\n{}",
				config);
		suite.setAttribute(SuiteManListener.CAP_CONFIG, config);

		config.validate();

		DriverType driverType = config.getDriverType();

		if (driverType.isAndroidPlatform()) {

			DeviceStoreFactory.create(MobilePlatformType.Android);
			ISuiteListener suiteListener = new AndroidStartupListener();
			suiteListener.onStart(suite);

			for (Device device : DeviceStoreFactory.getDeviceStore()
					.getDevices()) {
				if (OS.isFamilyDOS()) {
					appiumServers.put(device, new WinAppiumServer(device));
				} else {
					appiumServers.put(device, new LinuxAppiumServer(device));
				}
			}

		} else if (driverType.isIOSPlatform()) {
			DeviceStoreFactory.create(MobilePlatformType.iOS);
			IOSStartupListener ioslistener = new IOSStartupListener();
			ioslistener.onExecutionStart(suite);

			for (Device device : DeviceStoreFactory.getDeviceStore()
					.getDevices()) {
				appiumServers.put(device, new MacAppiumServer(device));
			}
		}

		logger.info("initial Run and Job info");

	}

	@Override
	public void onFinish(ISuite suite) {

		logger.info("suite:{} run finished", suite.getName());
		for (Device device : DeviceStoreFactory.getDeviceStore().getDevices()) {
			AppiumServer as = getAppiumServerWithDevice(device);
			if (as.isRunning()) {
				as.stopAppium();
			}
		}
		jobSetUpListener.onExecutionFinish();

	}

	private Map<String, String> updateConfigByPropertiesFile(ISuite suite) {

		Map<String, String> propertyConfig = getProperties();

		Map<String, String> testngConfig = suite.getXmlSuite().getParameters();

		testngConfig.putAll(propertyConfig);

		suite.getXmlSuite().setParameters(testngConfig);

		return testngConfig;

	}

	private Map<String, String> getProperties() {

		HashMap<String, String> propertiesMap = Maps.newHashMap();

		Properties properties = new Properties();
		try {
			InputStream inputStream = AppiumSuiteListener.class
					.getResourceAsStream(PROPERTIES_CONFIG_FILE);
			
			if(inputStream!=null){
				properties.load(inputStream);
			}
			
		} catch (Exception e) {

			throw new CapException(
					"fail to read properties from "
							+ PROPERTIES_CONFIG_FILE
							+ ". Please check whether both your test class and your config file are all under the src/test path. ");
		}

		for (String key : properties.stringPropertyNames()) {
			String value = properties.getProperty(key);
			propertiesMap.put(key, String.valueOf(value));
		}

		return propertiesMap;
	}

	public static AppiumServer getAppiumServerWithDevice(Device device) {
		return appiumServers.get(device);
	}

}
